package com.dana1.nos.util;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections.Factory;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.map.ReferenceIdentityMap;

/** Provides access to identity based meta information */
public class MetaSupport {
	/** map to extend objects with meta maps that expire when their parent objects are gc'd */
	@SuppressWarnings({ "unchecked" })
	private static final Map<? extends Serializable, Map<MetaKey<?>,Object>> metaMap = 
	(
			Collections.synchronizedMap
			(
					LazyMap.decorate 
					(
							new ReferenceIdentityMap(ReferenceIdentityMap.WEAK,ReferenceIdentityMap.HARD), 
							new Factory() {
								@Override
								public Object create() {
									return new HashMap<>();
								}
							}
					)
			)
	);

	/** Allows a key to incorporate a compile time type for genericized get and put operations */
	public static class MetaKey<T> {
		private String label;
		public MetaKey(String label) {
			this.label = label;
		}
		@Override
		public String toString() {
			return label;
		}
	}

	/** for the given target object, sets the meta for a key */
	@SuppressWarnings("unchecked")
	public static <T> T meta(Serializable target, MetaKey<T> key) {
		return (T)metaMap.get(target).get(key);
	}

	/** for the given target object, sets the meta for a key */
	public static <T> void meta(Serializable target, MetaKey<T> key, T value) {
		metaMap.get(target).put(key, value);
	}

}
